package com.jeesite.modules.digitalize.util.pdf;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.jeesite.modules.digitalize.constants.TaskReviewStatusEnum;
import com.jeesite.modules.digitalize.constants.TaskStatusEnum;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentNote;
import com.jeesite.modules.digitalize.entity.DigitalizeTaskAnnex;
import com.jeesite.modules.digitalize.entity.DigitalizeTaskReview;
import com.jeesite.modules.digitalize.entity.vo.DigitalizeTaskInfoVO;
import com.jeesite.modules.digitalize.util.minio.MinioFileUtil;
import com.jeesite.modules.sys.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author zhaoshuaixiang
 * @date 2023/11/16 18:28
 */
@Slf4j
@Configuration
public class PdfUtil {

    @Autowired
    private MinioFileUtil minioFileUtil;

    public MultipartFile createPdf(DigitalizeTaskInfoVO digitalizeTask, User loginUser, Map<String, String> userMap) {
        //常用的有paragraph段落、phrase语句块、chunk最小单位块
        try {
            // 设置响应头，控制浏览器下载该文件
//            response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(digitalizeTask.getTaskName() + ".pdf", "UTF-8"));
            //生成临时文件
            File tempFile = File.createTempFile(URLEncoder.encode(digitalizeTask.getTaskName(), "UTF-8"), ".pdf");
            // 获取文件路径
            String canonicalPath = tempFile.getCanonicalPath();
            log.info("canonicalPath----->" + canonicalPath);
            // 创建输出流
            FileOutputStream out = new FileOutputStream(canonicalPath);
//            OutputStream out = response.getOutputStream();

            Document doc = new Document(PageSize.A4);
            PdfWriter writer = PdfWriter.getInstance(doc, out);
            doc.open();

            //任务头部4行
            PdfPTable top4Table = new PdfPTable(new float[]{1f, 4f, 1f, 4f});
            top4Table.setWidthPercentage(100);
            //-------------------第一行----------------------
            top4Table.addCell(createParagraphCell("项目名称"));
            top4Table.addCell(createParagraphCell(digitalizeTask.getTaskName(), 3, 1));
            //-------------------第二行----------------------
            top4Table.addCell(createParagraphCell("创建人"));
            top4Table.addCell(createParagraphCell(digitalizeTask.getUserName()));
            top4Table.addCell(createParagraphCell("任务状态"));
            top4Table.addCell(createParagraphCell(TaskStatusEnum.getByCode(digitalizeTask.getTaskStatus()).getDesc()));
            //-------------------第三行----------------------
            top4Table.addCell(createParagraphCell("任务描述"));
            top4Table.addCell(createParagraphCell(digitalizeTask.getTaskRemarks(), 3, 1));
            //-------------------第四行----------------------
            top4Table.addCell(createParagraphCell("归档人"));
            top4Table.addCell(createParagraphCell(loginUser.getUserName()));
            top4Table.addCell(createParagraphCell("归档时间"));
            top4Table.addCell(createParagraphCell(DateUtil.now()));
            doc.add(top4Table);


            //获取流程数量设置行数
            int reviewCount = digitalizeTask.getReviewList().size() + 1;

            //-------------------任务详情----------------------

            //开始流程
            PdfPTable taskTable = new PdfPTable(new float[]{1f, 9f});
            taskTable.setWidthPercentage(100);
            taskTable.addCell(createParagraphCell("任务详情", 1, reviewCount));
            //任务右
            PdfPTable taskTableRightTable = new PdfPTable(new float[]{1f, 2f, 5f, 2f});
            taskTableRightTable.setWidthPercentage(100);
            taskTableRightTable.addCell(create0BorderParagraphCell("开始", 4, 1));
            //初始的流程要加上 [新建、提交]两行
            int noteNum = CollectionUtil.isEmpty(digitalizeTask.getNoteList())?0:digitalizeTask.getNoteList().size();
            int labelNum = CollectionUtil.isEmpty(digitalizeTask.getLabelList())?0:digitalizeTask.getLabelList().size();
            int fileNum = CollectionUtil.isEmpty(digitalizeTask.getFileList())?0:digitalizeTask.getFileList().size();
            int eadRowspan = noteNum + labelNum + fileNum + 2;
            taskTableRightTable.addCell(create0BorderParagraphCell("负责人", 1, eadRowspan));
            taskTableRightTable.addCell(create0BorderParagraphCell("新建了任务"));
            taskTableRightTable.addCell(create0BorderParagraphCell(""));
            taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(digitalizeTask.getCreateDate())));
            //批注、标签、文件
            buildTaskNoteOrLabelOrFile(taskTableRightTable, digitalizeTask.getNoteList(), digitalizeTask.getLabelList(), digitalizeTask.getFileList());
            if (digitalizeTask.getSubmitDate() != null) {
                //提交时间
                taskTableRightTable.addCell(create0BorderParagraphCell("提交了任务"));
                taskTableRightTable.addCell(create0BorderParagraphCell(""));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(digitalizeTask.getSubmitDate())));
            }
            taskTable.addCell(createPdfPTable(taskTableRightTable));
            //审核流程
            buildTaskReview(digitalizeTask.getReviewList(), taskTable);

            //-------------批注
            buildNoteOrLabel("批注", taskTable, digitalizeTask, userMap);
            //-------------标签
            buildNoteOrLabel("标签", taskTable, digitalizeTask, userMap);
            //-------------附件
            buildFile(taskTable, digitalizeTask);

            doc.add(taskTable);
            doc.close();
            writer.close();
            MultipartFile file = new MockMultipartFile("file", tempFile.getName(), MediaType.APPLICATION_PDF_VALUE, new FileInputStream(tempFile));
            tempFile.delete();
            return file;
        } catch (Exception e) {
            log.error("pdf导出失败", e);
            throw new RuntimeException("pdf导出失败");
        }
    }

    private void buildFile(PdfPTable taskTable, DigitalizeTaskInfoVO digitalizeTas) throws DocumentException, IOException {
        taskTable.addCell(createParagraphCell("附件"));
        PdfPTable fileTableRightTable = new PdfPTable(new float[]{1f});
        fileTableRightTable.setWidthPercentage(100);
        fileTableRightTable.addCell(createParagraphCell("开始"));
        //提交时的
        if (CollUtil.isNotEmpty(digitalizeTas.getFileList())) {
            for (DigitalizeTaskAnnex e : digitalizeTas.getFileList()) {
                fileTableRightTable.addCell(createParagraphCell(e.getFileName()));
            }
        }
        for (DigitalizeTaskReview e : digitalizeTas.getReviewList()) {
            fileTableRightTable.addCell(createParagraphCell(e.getStageName()));
            if (CollUtil.isNotEmpty(e.getFileList())) {
                for (DigitalizeTaskAnnex ee : e.getFileList()) {
                    fileTableRightTable.addCell(createParagraphCell(ee.getFileName()));
                }
            }
        }
        taskTable.addCell(createPdfPTable(fileTableRightTable));
    }

    private void buildNoteOrLabel(String type, PdfPTable taskTable, DigitalizeTaskInfoVO digitalizeTas, Map<String, String> userMap) throws DocumentException, IOException {
        taskTable.addCell(createParagraphCell(type));
        PdfPTable noteTableRightTable = new PdfPTable(new float[]{3f, 5f, 2f});
        noteTableRightTable.setWidthPercentage(100);
        noteTableRightTable.addCell(create0BorderParagraphCell("开始", 3, 1));
        //提交时的
        List<DigitalizeComponentNote> list = "批注".equals(type) ? digitalizeTas.getNoteList() : digitalizeTas.getLabelList();
        if (CollUtil.isNotEmpty(list)) {
            for (DigitalizeComponentNote e : list) {
                noteTableRightTable.addCell(create0BorderParagraphCell(e.getNoteContent()));
                noteTableRightTable.addCell(create0BorderParagraphCell(userMap.getOrDefault(e.getCreateBy(), "")));
                noteTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getCreateDate())));
                noteTableRightTable.addCell(create0BorderParagraphCell(""));
                noteTableRightTable.addCell(createImageCell(e.getFileUrl()));
                noteTableRightTable.addCell(create0BorderParagraphCell(""));
            }
        }
        //流程时的
        for (DigitalizeTaskReview e : digitalizeTas.getReviewList()) {
            noteTableRightTable.addCell(createParagraphCell(e.getStageName(), 3, 1));
            List<DigitalizeComponentNote> reviewList = "批注".equals(type) ? e.getNoteList() : e.getLabelList();
            if (CollUtil.isNotEmpty(reviewList)) {
                for (DigitalizeComponentNote e1 : reviewList) {
                    noteTableRightTable.addCell(create0BorderParagraphCell(e1.getNoteContent()));
                    noteTableRightTable.addCell(create0BorderParagraphCell(userMap.getOrDefault(e.getCreateBy(), "")));
                    noteTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e1.getCreateDate())));
                    noteTableRightTable.addCell(create0BorderParagraphCell(""));
                    noteTableRightTable.addCell(createImageCell(e1.getFileUrl()));
                    noteTableRightTable.addCell(create0BorderParagraphCell(""));
                }
            }
        }
        taskTable.addCell(createPdfPTable(noteTableRightTable));
    }

    private void buildTaskReview(List<DigitalizeTaskReview> reviewList, PdfPTable taskTable) throws DocumentException, IOException {
        for (int i = 0; i < reviewList.size(); i++) {
            DigitalizeTaskReview e = reviewList.get(i);
            //任务右
            PdfPTable taskTableRightTable = new PdfPTable(new float[]{1f, 2f, 5f, 2f});
            taskTableRightTable.setWidthPercentage(100);
            taskTableRightTable.addCell(create0BorderParagraphCell(e.getStageName(), 4, 1));
            List<DigitalizeComponentNote> noteList = CollUtil.isEmpty(e.getNoteList()) ? new ArrayList<>() : e.getNoteList();
            List<DigitalizeComponentNote> labelList = CollUtil.isEmpty(e.getLabelIdList()) ? new ArrayList<>() : e.getLabelList();
            List<DigitalizeTaskAnnex> fileList = CollUtil.isEmpty(e.getFileList()) ? new ArrayList<>() : e.getFileList();

            int eadRowspan = noteList.size() + labelList.size() + fileList.size();
            //是否有答复
            if (StrUtil.isNotBlank(e.getReply())) {
                eadRowspan++;
            }
            //是否有审核
            if (StrUtil.isNotBlank(e.getRemarks())) {
                eadRowspan++;
            }
            //是否是最后一个审核
            boolean isLast = false;
            if (i == reviewList.size() - 1) {
                eadRowspan++;
                isLast = true;
            }
            taskTableRightTable.addCell(create0BorderParagraphCell("负责人", 1, eadRowspan));
            //答复
            if (StrUtil.isNotBlank(e.getReply())) {
                taskTableRightTable.addCell(create0BorderParagraphCell("答复了任务"));
                taskTableRightTable.addCell(create0BorderParagraphCell(e.getReply()));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getCreateDate())));
            }
            //批注、标签、文件
            buildTaskNoteOrLabelOrFile(taskTableRightTable, noteList, labelList, fileList);
            //审核
            if (StrUtil.isNotBlank(e.getRemarks())) {
                taskTableRightTable.addCell(create0BorderParagraphCell(TaskReviewStatusEnum.COMPLETED.getCode().equals(e.getStatus()) ? "通过了任务" : "驳回了任务"));
                taskTableRightTable.addCell(create0BorderParagraphCell(e.getRemarks()));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getUpdateDate())));
            }
            if (isLast) {
                taskTableRightTable.addCell(create0BorderParagraphCell("完成了任务"));
                taskTableRightTable.addCell(create0BorderParagraphCell(""));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getUpdateDate())));
            }
            taskTable.addCell(createPdfPTable(taskTableRightTable));
        }

    }

    private void buildTaskNoteOrLabelOrFile(PdfPTable taskTableRightTable,
                                            List<DigitalizeComponentNote> noteList,
                                            List<DigitalizeComponentNote> labelList,
                                            List<DigitalizeTaskAnnex> fileList) throws DocumentException, IOException {
        if (CollUtil.isNotEmpty(noteList)) {
            //批注
            for (DigitalizeComponentNote e : noteList) {
                taskTableRightTable.addCell(create0BorderParagraphCell("添加了批注"));
                taskTableRightTable.addCell(create0BorderParagraphCell(e.getNoteContent()));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getCreateDate())));
            }
        }
        if (CollUtil.isNotEmpty(labelList)) {
            //标签
            for (DigitalizeComponentNote e : labelList) {
                taskTableRightTable.addCell(create0BorderParagraphCell("添加了标签"));
                taskTableRightTable.addCell(create0BorderParagraphCell(e.getNoteContent()));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getCreateDate())));
            }
        }
        if (CollUtil.isNotEmpty(fileList)) {
            //附件
            for (DigitalizeTaskAnnex e : fileList) {
                taskTableRightTable.addCell(create0BorderParagraphCell("上传了附件"));
                taskTableRightTable.addCell(create0BorderParagraphCell(e.getFileName()));
                taskTableRightTable.addCell(create0BorderParagraphCell(dateFormat(e.getCreateDate())));
            }
        }
    }

    private PdfPCell createParagraphCell(String value) throws DocumentException, IOException {
        return createParagraphCell(value, 1, 1);
    }

    private PdfPCell createParagraphCell(String value, int colspan, int rowspan) throws DocumentException, IOException {
        return createParagraphCell(value, colspan, rowspan, true);
    }

    private PdfPCell create0BorderParagraphCell(String value) throws DocumentException, IOException {
        return create0BorderParagraphCell(value, 1, 1);
    }

    private PdfPCell create0BorderParagraphCell(String value, int colspan, int rowspan) throws DocumentException, IOException {
        return createParagraphCell(value, colspan, rowspan, false);
    }

    private PdfPCell createParagraphCell(String value, int colspan, int rowspan, boolean border) throws DocumentException, IOException {
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese);
        PdfPCell cell = new PdfPCell(new Paragraph(value, fontChinese));
        cell.setColspan(colspan);
        cell.setRowspan(rowspan);
        if (!border) {
            cell.setBorder(Rectangle.NO_BORDER);
        }
        cell.setFixedHeight(20f);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        return cell;
    }


    private PdfPCell createPdfPTable(PdfPTable taskTableRightTable) {
        taskTableRightTable.getDefaultCell().setBorder(Rectangle.NO_BORDER);
        return new PdfPCell(taskTableRightTable);
    }

    private String dateFormat(Date date) {
        return DateUtil.format(date, "yyyy-MM-dd HH:mm");
    }

    private PdfPCell createImageCell(String url) throws IOException, BadElementException {
        Image instance = Image.getInstance(new URL(minioFileUtil.getPreviewFileUrl(url)), true);
        PdfPCell cell = new PdfPCell(instance, true);
        cell.setBorder(Rectangle.NO_BORDER);
//        cell.setFixedHeight(40f);
        return cell;
    }

}
